#ifndef _H_IN_
#define _H_IN_

#ifdef __cplusplus
extern "C" {
#endif

#include "carmela_util.h"
#include "carmela_sdk.h"

#include "carmela_broker.h"

#define MQ_BROKER_RETURN_SESSION_IS_BUSY	100
#define MQ_BROKER_RETURN_FETCH_ONE		200
#define MQ_BROKER_RETURN_FETCH_NOTHING		400
#define MQ_BROKER_RETURN_FATAL			-1

struct MQBroker ;
struct MQStore ;
struct MQTopic ;
struct MQSubscribeGroup ;
struct MQFileMapping ;

/*
 * comm
 */

#define MQ_LONG_PULL_AS_SERVER_STATUS_FIRST_SEND_BEFORE_SILENT	1
#define MQ_LONG_PULL_AS_SERVER_STATUS_LAST_RECV_BEFORE_SILENT	2
#define MQ_LONG_PULL_AS_SERVER_STATUS_SILENT			3
#define MQ_LONG_PULL_AS_SERVER_STATUS_LAST_SEND_AFTER_SILENT	4

#define MQ_PRODUCE_DELAY_MESSAGE_EVENT		1

struct MQAcceptedSession
{
	int			accepted_sock ;
	struct sockaddr_in	accepted_address ;
	char			client_ip[ 40 + 1 ] ;
	int			client_port ;
	
	struct TcpdaemonServerEnvironment
				*p_tcpdaemon_env ;
	void			*tcpdaemon_session ;
	
	struct TDHBContext	tdhb ;
	struct AppendBuffer	*comm_data ;
	uint16_t		comm_status ;
	
	struct MQBroker		*broker ;
	
	struct MQSubscribeGroup	*p_subscribe_group ;
	uint16_t		long_pull_as_server_status ;
	struct list_head	subscribe_group_subscribe_session_list_node ;
	
	struct list_head	msg_file_subscribe_session_list_node ; /* struct MQFileMapping */
	struct list_head	topic_file_subscribe_session_list_node ; /* struct MQFileMapping */
} ;

int CloseAcceptedSession( struct MQAcceptedSession *p_accepted_session );

func_tcpmain tcpmain ;

/*
 * broker
 */

#define MQ_BROKER_DATA_PATH_DEFAULT	"carmela_data"

struct MQBroker
{
	struct TcpdaemonEntryParameter	entry ;
	
	unsigned char			tcp_nodelay ;
	char				data_path[ PATH_MAX ] ;
	size_t				msg_file_size ;
	size_t				topic_file_size ;
	size_t				delay_msg_file_size ;
	size_t				msg_file_list_nodes_soft_max ;
	size_t				msg_file_list_nodes_hard_max ;
	size_t				topic_file_list_nodes_soft_max ;
	size_t				topic_file_list_nodes_hard_max ;
	size_t				delay_msg_file_list_nodes_soft_max ;
	
	struct rb_root			store_name_tree ; /* struct MQStore */
} ;

/*
 * subscribe group
 */

struct MQSubscribeGroup
{
	char			subscribe_group_name[ MQ_SUBSCRIBE_GROUP_NAME_MAX_LEN+1 ] ;
	uint8_t			subscribe_group_name_len ;
	struct rb_node		subscribe_group_name_tree_node ;
	
	struct MQStore		*p_store ;
	struct MQFileMapping	*msg_file ;
	struct MQTopic		*p_topic ;
	struct MQFileMapping	*topic_file ;
	char			*topic_fill_ptr ;
	uint64_t		topic_fill_step ;
	
	struct list_head	subscribe_session_list ; /* struct MQAcceptedSession */
} ;

int LinkSubscribeGroupNameTreeNode( struct MQTopic *topic , struct MQSubscribeGroup *subsribe_group );
void UnlinkSubscribeGroupNameTreeNode( struct MQTopic *topic , struct MQSubscribeGroup *subsribe_group );
struct MQSubscribeGroup *QuerySubscribeGroupNameWithLenTreeNode( struct MQTopic *topic , struct MQSubscribeGroup *subsribe_group );
struct MQSubscribeGroup *TravelSubscribeGroupNameTreeNode( struct MQTopic *topic , struct MQSubscribeGroup *subsribe_group );
void DestroySubscribeGroupNameTree( struct MQTopic *topic );

/*
 * app
 */

int DispatchProcess( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );

int app_CreateStore( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );
int app_DestroyStore( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );
int app_CreateTopic( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );
int app_DestroyTopic( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );
int app_ProduceMessage( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );
int app_AddDelayMessage( struct TcpdaemonServerEnvironment *p_env , struct MQDelayMessage *delay_msg );
int app_SubscribeMessage( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );
int app_ConsumeMessage( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );
int app_Heartbeat( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );
int app_HeartbeatResponse( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );
int app_ProduceDelayMessage( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );
int app_CancelDelayMessage( struct TcpdaemonServerEnvironment *p_env , struct MQAcceptedSession *p_accepted_session );

int FetchSubscribeGroupMessageToAcceptedSession( struct TcpdaemonServerEnvironment *p_env , struct MQSubscribeGroup *subscribe_group , struct MQAcceptedSession *p_accepted_session );
int FetchSubscribeGroupMessage( struct TcpdaemonServerEnvironment *p_env , struct MQSubscribeGroup *p_subscribe_group );
int FetchTopicMessage( struct TcpdaemonServerEnvironment *p_env , struct MQTopic *topic );

#ifdef __cplusplus
}
#endif

#endif

